package frame

import (
	"embed"
	"fmt"
	"gitee.com/git_public/vfaith/builtin/bean"
	"gitee.com/git_public/vfaith/builtin/shape"
	"gitee.com/git_public/vfaith/sugar"
	"gitee.com/git_public/vfaith/sugar/reflectx"
	"log"
)

var fb *FaithBuilder

type FaithBuilder struct {
	routerMap *shape.MapGnc[bean.IxBaseRouter]
	actionMap *shape.MapGnc[IxBaseAction]
	bizMap    *shape.MapGnc[IxBaseBiz]
	daoMap    *shape.MapGnc[IxBaseDao]
}

func init() {
	fb = &FaithBuilder{
		routerMap: shape.NewMapGnc[bean.IxBaseRouter](),
		actionMap: shape.NewMapGnc[IxBaseAction](),
		bizMap:    shape.NewMapGnc[IxBaseBiz](),
		daoMap:    shape.NewMapGnc[IxBaseDao](),
	}
}

func GetFB() *FaithBuilder {
	return fb
}

func InitFaithBuilder(fs *embed.FS) *FaithBuilder {
	log.Printf("********************实例化MVC【%v】********************", "Start")
	fb.daoMap.RangeStoreReflect("DaoInitialize")
	fb.bizMap.RangeStoreReflect("BizInitialize")
	fb.actionMap.RangeStoreReflect("ActionInitialize")
	log.Printf("********************实例化MVC【%v】********************", "End")

	// 根据注释自动化注册http
	fb.actionMap.RangeStoreMap(func(k string, structTyp IxBaseAction) {
		log.Printf("---------------------------------------------")
		log.Printf("HttpAction注册【%s】", k)
		RouterRegister(structTyp, fs)
	})

	return fb
}

func RouterRegistry[T bean.IxBaseRouter](router T, nameSlice ...string) T {
	routerName := router.AppName()
	if _, exist := fb.routerMap.Get(routerName); exist {
		log.Fatalf("系统异常，对象【%s】重复注册", routerName)
	}
	//router := reflectx.NewInstance[T]()
	fb.routerMap.Add(routerName, router)
	return router
}

func GetRouter(routerName string, nameSlice ...string) bean.IxBaseRouter {
	if ixObj, exist := fb.routerMap.Get(routerName); exist {
		return ixObj
	} else {
		//log.Fatalf("系统异常，对象【%s】不存在", routerName)
		return nil
	}
}

func ActionRegistry[T IxBaseAction](nameSlice ...string) T {
	actionName := fmtKey(nameSlice, reflectx.TypName[T](), "action")
	if _, exist := fb.actionMap.Get(actionName); exist {
		log.Fatalf("系统异常，对象【%s】重复注册", actionName)
	}
	action := reflectx.NewInstance[T]()
	fb.actionMap.Add(actionName, action)
	return action
}

func GetAction[T IxBaseAction](nameSlice ...string) T {
	var zero T
	actionName := fmtKey(nameSlice, reflectx.TypName[T](), "action")
	if ixObj, exist := fb.actionMap.Get(actionName); exist {
		if obj, ok := ixObj.(T); ok {
			return obj
		} else {
			log.Fatalf("系统异常，对象【%s】断言失败", actionName)
		}
	} else {
		log.Fatalf("系统异常，对象【%s】不存在", actionName)
	}
	return zero
}

func BizRegistry[T IxBaseBiz](nameSlice ...string) T {
	bizName := fmtKey(nameSlice, reflectx.TypName[T](), "biz")
	if _, exist := fb.bizMap.Get(bizName); exist {
		log.Fatalf("系统异常，对象【%s】重复注册", bizName)
	}
	action := reflectx.NewInstance[T]()
	fb.bizMap.Add(bizName, action)
	return action
}

func GetBiz[T IxBaseBiz](nameSlice ...string) T {
	var zero T
	bizName := fmtKey(nameSlice, reflectx.TypName[T](), "biz")
	if ixObj, exist := fb.bizMap.Get(bizName); exist {
		if obj, ok := ixObj.(T); ok {
			return obj
		} else {
			log.Fatalf("系统异常，对象【%s】断言失败", bizName)
		}
	} else {
		log.Fatalf("系统异常，对象【%s】不存在", bizName)
	}
	return zero
}

func DaoRegistry[T IxBaseDao](nameSlice ...string) T {
	daoName := fmtKey(nameSlice, reflectx.TypName[T](), "dao")
	if _, exist := fb.daoMap.Get(daoName); exist {
		log.Fatalf("系统异常，对象【%s】重复注册", daoName)
	}
	action := reflectx.NewInstance[T]()
	fb.daoMap.Add(daoName, action)
	return action
}

func GetDao[T IxBaseDao](nameSlice ...string) T {
	var zero T
	daoName := fmtKey(nameSlice, reflectx.TypName[T](), "dao")
	if ixObj, exist := fb.daoMap.Get(daoName); exist {
		if obj, ok := ixObj.(T); ok {
			return obj
		} else {
			log.Fatalf("系统异常，对象【%s】断言失败", daoName)
		}
	} else {
		log.Fatalf("系统异常，对象【%s】不存在", daoName)
	}
	return zero
}

func fmtKey(nameSlice []string, beanName string, typeName string) string {
	var moduleName string
	if len(nameSlice) > 0 {
		moduleName = nameSlice[0]
	} else if typeName == "action" {
		moduleName = sugar.GetPkgParent(3)
	} else {
		moduleName = sugar.GetPkgParent(3)
	}

	return fmt.Sprintf("%s|||%s", moduleName, beanName)
}
